﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Logging;
using System.IO;
using System.ComponentModel.Composition;
using RenderEngineInterfaces;
using DeepZoomPivotConstructor.ErrorAndLoggingInterfaces;

namespace t_Utilities
{
    /// <summary>
    /// Test out the logger test.
    /// </summary>
    [TestClass]
    public class t_Logger
    {
        public t_Logger()
        {
        }

        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        //
        // You can use the following additional attributes as you write your tests:
        //
        // Use ClassInitialize to run code before running the first test in the class
        // [ClassInitialize()]
        // public static void MyClassInitialize(TestContext testContext) { }
        //
        // Use ClassCleanup to run code after all tests in a class have run
        // [ClassCleanup()]
        // public static void MyClassCleanup() { }
        //
        // Use TestInitialize to run code before running each test 
        // [TestInitialize()]
        // public void MyTestInitialize() { }
        //
        // Use TestCleanup to run code after each test has run
        // [TestCleanup()]
        // public void MyTestCleanup() { }
        //
        #endregion

        [TestInitialize]
        public void InitTestFramework()
        {
        }

        [TestMethod]
        public void TestDefaultLogging()
        {
            LoggerFile lf = new LoggerFile();
            lf.LogMessage("test", "this is a test of all that has gone wrong");
        }

        [TestMethod]
        public void TestLogDirExists()
        {
            FileInfo f = new FileInfo("TestLogDirExists\\errors.txt");
            if (f.Directory.Exists)
            {
                f.Directory.Delete();
            }
            LoggerFile lf = new LoggerFile(f);
            lf.LogMessage("ho", "ho ho");

            f.Refresh();
            Assert.IsTrue(f.Exists, "The file doesn't seem to exist!");
        }

        [TestMethod]
        public void TestWriteToFile()
        {
            /// Test writing a message to a file
            FileInfo f = new FileInfo("test-log.txt");
            if (f.Exists)
            {
                f.Delete();
            }
            LoggerFile lf = new LoggerFile(f);
            lf.LogMessage("dude", "yo my holy cow!");
            FileInfo f1 = new FileInfo("test-log.txt");
            Assert.IsTrue(f1.Exists, "Log file does not exist");
            Assert.IsTrue(f1.Length > 25, "Output file is too small");
            long len = f1.Length;

            lf.LogMessage("dude", "yo my holy cow!");
            FileInfo f2 = new FileInfo("test-log.txt");
            Assert.IsTrue(f2.Length >= len * 2 - 5, "Lenght didn't double when we wrote the second log message");
        }

        [TestMethod]
        public void TestWriteException()
        {
            /// Test writing a message to a file
            FileInfo f = new FileInfo("test-log.txt");
            if (f.Exists)
            {
                f.Delete();
            }
            LoggerFile lf = new LoggerFile(f);

            try
            {
                int i = 10;
                i = i + 1;
                throw new SystemException("ops - bad things have happened");
            } catch (Exception e)
            {
                lf.LogMessage("yo", "failed!", e);
            }
        }

        /// <summary>
        /// Used to test the auto-instantiation of this guy!
        /// </summary>
        [Import]
        private IErrorLogger MyLogger { get; set; }

        [TestMethod]
        public void TestMEFLogbuilder()
        {
            t_TestingLibrary.Utilities.MyClassInit();
            t_TestingLibrary.Utilities.AddAssemblyForType(typeof(LoggerFile));
            t_TestingLibrary.Utilities.Compose(this);

            Assert.IsNotNull(MyLogger);
            MyLogger.LogMessage("fork", "as in, put one in it!");

            t_TestingLibrary.Utilities.MyClassDone();
        }

        [TestMethod]
        public void TestLogMove()
        {
            DirectoryInfo dir1 = new DirectoryInfo("TestLogMove1");
            if (dir1.Exists)
            {
                dir1.Delete();
            }
            FileInfo file1 = new FileInfo(dir1.FullName + "\\errors.txt");
            DirectoryInfo dir2 = new DirectoryInfo("TestLogMove2");
            if (dir2.Exists)
            {
                dir2.Delete();
            }
            FileInfo file2 = new FileInfo(dir2.FullName + "\\errors.txt");

            LoggerFile lf = new LoggerFile(file1);
            lf.LogMessage("fork", "fork it over");
            lf.SetLogfileLocation(dir2);

            file2.Refresh();
            Assert.IsTrue(file2.Exists, "Moved log file does not exist!");

            using (var rdr = file2.OpenText())
            {
                var contents = rdr.ReadToEnd();
                Assert.IsTrue(contents.Contains("fork it over"), "Log file doesn't seem to contain the proper error message!");
            }

            long oldLen = file2.Length;
            lf.LogMessage("fork2", "fork it over again!");
            file2.Refresh();
            Assert.AreNotEqual(oldLen, file2.Length, "The size of the log file should have changed!");
        }

        [TestMethod]
        public void TestLogMoveNoSourceFile()
        {
            ///
            /// THe log file is empty - and the move shoudl work just fine!
            /// 

            DirectoryInfo dir1 = new DirectoryInfo("TestLogMoveNoSourceFile");
            DirectoryInfo dir2 = new DirectoryInfo("TestLogMoveNoSourceFile-copied");
            FileInfo f1 = new FileInfo(dir1.FullName + "\\errors.txt");

            LoggerFile lf = new LoggerFile(f1);
            f1.Refresh();
            Assert.IsFalse(f1.Exists);
            lf.SetLogfileLocation(dir2);
        }

        [TestMethod]
        public void TestLogMoveTwice()
        {
            DirectoryInfo dir1 = new DirectoryInfo("TestLogMoveTwice1");
            if (dir1.Exists)
            {
                dir1.Delete();
            }
            FileInfo file1 = new FileInfo(dir1.FullName + "\\errors.txt");

            DirectoryInfo dir2 = new DirectoryInfo("TestLogMoveTwice2");
            if (dir2.Exists)
            {
                dir2.Delete();
            }
            FileInfo file2 = new FileInfo(dir2.FullName + "\\errors.txt");

            {
                LoggerFile lf = new LoggerFile(file1);
                lf.LogMessage("fork", "fork it over");
                lf.SetLogfileLocation(dir2);
            }

            {
                LoggerFile lf = new LoggerFile(file1);
                lf.LogMessage("fork", "fork it over");
                lf.SetLogfileLocation(dir2);
            }

            Assert.AreEqual(2, dir2.EnumerateFiles().Count(), "Expected two log files after two moves!");
        }

        [TestMethod]
        public void TestNoChange()
        {
            DirectoryInfo dir1 = new DirectoryInfo("TestNoChange1");
            if (dir1.Exists)
            {
                dir1.Delete();
            }
            FileInfo file1 = new FileInfo(dir1.FullName + "\\errors.txt");

            DirectoryInfo dir2 = new DirectoryInfo("TestNoChange2");
            if (dir2.Exists)
            {
                dir2.Delete();
            }

            {
                FileInfo oldFile1 = new FileInfo(file1.FullName);
                LoggerFile lf = new LoggerFile(file1);
                lf.LogMessage("fork", "fork it over");
                lf.SetLogfileLocation(dir2);
                Assert.AreEqual(oldFile1.DirectoryName, file1.DirectoryName, "The file 1 should not have been 'moved'");
            }

        }
    }
}
